<template>
  <div ref="refContainer" class="container" @scroll="TableScroll">
    <div
      ref="refEditArea"
      class="edit-area"
      @mouseup="CellMouseEnd"
      @mouseleave="CellMouseEnd"
    >
      <!-- 列 -->
      <div class="col-number">
        <div
          v-for="(cell, index) in colIndex"
          class="cell-index"
          :style="[
            'top:0',
            'left:' + cell.left + 'px',
            'width:' + cell.width + 'px',
            'height:' + cell.height + 'px',
            'line-height:' + cell.height + 'px',
          ]"
        >
          {{ cell.label }}
          <div
            v-if="index > 1"
            class="moveColPointer moveColPointerLeft"
            @mousedown="UpdateCellWidth($event, index - 1)"
          ></div>
          <div
            v-if="index > 0"
            class="moveColPointer moveColPointerRight"
            @mousedown="UpdateCellWidth($event, index)"
          ></div>
        </div>
      </div>
      <!-- 行 -->
      <div class="row-number">
        <div
          v-for="(cell, index) in rowIndex"
          class="cell-index"
          :style="[
            'top:' + cell.top + 'px',
            'left:0',
            'width:' + cell.width + 'px',
            'height:' + cell.height + 'px',
            'line-height:' + cell.height + 'px',
          ]"
        >
          {{ cell.label }}
          <div
            v-if="index > 1"
            class="moveRowPointer moveRowPointerTop"
            @mousedown="UpdateCellHeight($event, index - 1)"
          ></div>
          <div
            v-if="index > 0"
            class="moveRowPointer moveRowPointerBottom"
            @mousedown="UpdateCellHeight($event, index)"
          ></div>
        </div>
      </div>
      <!-- 单元格 -->
      <div
        class="edit-cells"
        :style="[
          'top:' + colIndex[0].height + 'px',
          'left:' + rowIndex[0].width + 'px',
        ]"
      >
        <template v-for="(rows, rowNum) in cells">
          <template v-for="(cols, colNum) in rows">
            <div
              v-if="cols.show"
              class="cells"
              :style="[
                'top:' + cols.top + 'px',
                'left:' + cols.left + 'px',
                'width:calc(' + cols.width + 'px + ' + cols.colspan + 'px)',
                'height:calc(' + cols.height + 'px + ' + cols.rowspan + 'px)',
                'line-height:' + cols.height + 'px',

                'text-align:' + cols.textAlign,
                'font-weight:' + cols.bold,
                'font-style:' + cols.italic,
                'text-decoration:' + cols.underline,
                'fontSize:' + cols.fontSize + 'pt',
                'color:' + cols.color,
                'background:' + cols.background,
              ]"
              @click="CellClick(rowNum, colNum)"
              @mousedown="CellMouseDown(rowNum, colNum)"
              @mouseenter="CellMouseEnter(rowNum, colNum)"
            >
              <span
                v-if="nowInputPos.row != rowNum || nowInputPos.col != colNum"
              >
                {{ cols.text }}
              </span>
              <el-input
                ref="refNowInput"
                v-if="nowInputPos.row == rowNum && nowInputPos.col == colNum"
                :input-style="[
                  'width:calc(' + cols.width + 'px - 7px)',
                  'height:calc(' + cols.height + 'px - 1px)',

                  'text-align:' + cols.textAlign,
                  'font-weight:' + cols.bold,
                  'font-style:' + cols.italic,
                  'text-decoration:' + cols.underline,
                  'fontSize:' + cols.fontSize + 'pt',
                  'color:' + cols.color,
                  'background:' + cols.background,
                ]"
                v-model="nowInputInfo"
              />
            </div>
          </template>
        </template>
      </div>
    </div>
    <div class="range-select">
      <span
        v-if="range.show"
        class="range"
        :style="[
          'top:' + (range.top - 1) + 'px',
          'left:' + (range.left - 1) + 'px',
          'width:' + (range.width - 2) + 'px',
          'height:' + (range.height - 2) + 'px',
        ]"
        :class="{ more: range.more }"
      ></span>
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";
import { useRouter } from "vue-router";
import * as Table from "@/libs/table";
import { GetOffsetSize } from "@/libs/tool";

const router = useRouter();
const colIndex = ref([]);
const rowIndex = ref([]);
const cells = ref([]);
const range = ref({ show: false, more: false });

Table.InitTable({ colIndex, rowIndex, cells, range, router });

// ********** 框选及点击输入的操作 Start **********
//#region
const refNowInput = ref(null);
const nowInputPos = ref({ row: -1, col: -1 });
const nowInputInfo = ref("");

const CellMouseDown = (row, col) => {
  Table.UpdateRangeStart({ row, col });
};

const CellMouseEnter = (row, col) => {
  Table.UpdateRangeMove({ row, col });
};

const CellMouseEnd = () => {
  Table.UpdateRangeEnd();
};

const CellClick = (row, col) => {
  nowInputInfo.value = cells.value[row][col].text;
  nowInputPos.value = { row, col };

  document.addEventListener("mousedown", DocumentMouseDown);

  setTimeout(() => {
    refNowInput.value[0].focus();
  }, 0);
};

const DocumentMouseDown = () => {
  cells.value[nowInputPos.value.row][nowInputPos.value.col].text =
    nowInputInfo.value;
  nowInputInfo.value = "";
  nowInputPos.value = { row: -1, col: -1 };
  document.removeEventListener("mousedown", DocumentMouseDown);
};
//#endregion
// ********** 框选及点击输入的操作 End **********

// ********** 改变单元格的宽度和高度 Start **********
//#region
const refEditArea = ref(null);
let moveColLine;
let moveColIndex;
let moveRowLine;
let moveRowIndex;

const UpdateCellWidth = (event, index) => {
  moveColIndex = index;
  refEditArea.value.addEventListener("mousemove", UpdateColWidthMove);
  refEditArea.value.addEventListener("mouseup", UpdateColWidthEnd);
  refEditArea.value.addEventListener("mouseleave", UpdateColWidthEnd);

  let offset = GetOffsetSize(refEditArea.value);

  moveColLine = document.createElement("div");
  Object.assign(moveColLine.style, {
    position: "absolute",
    left: event.clientX - offset.x + "px",
    height: "100%",
    border: "1px dashed rgba(33, 115, 70, 0.7)",
    pointerEvents: "none",
  });
  refEditArea.value.appendChild(moveColLine);
};

const UpdateColWidthMove = (event) => {
  let offset = GetOffsetSize(refEditArea.value);
  Object.assign(moveColLine.style, {
    left: event.clientX - offset.x + "px",
  });
};

const UpdateColWidthEnd = () => {
  Table.UpdateColWidth({ index: moveColIndex, left: moveColLine.offsetLeft });
  refEditArea.value.removeEventListener("mousemove", UpdateColWidthMove);
  refEditArea.value.removeEventListener("mouseup", UpdateColWidthEnd);
  refEditArea.value.removeEventListener("mouseleave", UpdateColWidthEnd);
  refEditArea.value.removeChild(moveColLine);
};

const UpdateCellHeight = (event, index) => {
  moveRowIndex = index;
  refEditArea.value.addEventListener("mousemove", UpdateRowHeightMove);
  refEditArea.value.addEventListener("mouseup", UpdateRowHeightEnd);
  refEditArea.value.addEventListener("mouseleave", UpdateRowHeightEnd);

  let offset = GetOffsetSize(refEditArea.value);

  moveRowLine = document.createElement("div");
  Object.assign(moveRowLine.style, {
    position: "absolute",
    top: event.clientY - offset.y + "px",
    width: "100%",
    border: "1px dashed rgba(33, 115, 70, 0.7)",
    pointerEvents: "none",
  });
  refEditArea.value.appendChild(moveRowLine);
};

const UpdateRowHeightMove = (event) => {
  let offset = GetOffsetSize(refEditArea.value);
  Object.assign(moveRowLine.style, {
    top: event.clientY - offset.y + "px",
  });
};

const UpdateRowHeightEnd = () => {
  Table.UpdateRowHeight({ index: moveRowIndex, top: moveRowLine.offsetTop });
  refEditArea.value.removeEventListener("mousemove", UpdateRowHeightMove);
  refEditArea.value.removeEventListener("mouseup", UpdateRowHeightEnd);
  refEditArea.value.removeEventListener("mouseleave", UpdateRowHeightEnd);
  refEditArea.value.removeChild(moveRowLine);
};
//#endregion
// ********** 改变单元格的宽度和高度 End **********

// ********** 单元格虚拟化 Start **********
//#region
const refContainer = ref(null);

const TableScroll = () => {
  /* Table.VirtualTable(refContainer.value); */
};
//#endregion
// ********** 单元格虚拟化 End **********
</script>

<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100%;
  overflow: scroll;
  position: relative;

  .edit-area {
    .col-number {
      position: absolute;
      top: 0;
      width: 100%;

      .moveColPointer {
        position: absolute;
        top: 0;
        width: 5px;
        height: 100%;
        cursor: col-resize;
      }

      .moveColPointerLeft {
        left: 0px;
      }

      .moveColPointerRight {
        right: 0px;
      }
    }

    .row-number {
      position: absolute;
      left: 0;
      height: 100%;

      .moveRowPointer {
        position: absolute;
        left: 0;
        width: 100%;
        height: 5px;
        cursor: row-resize;
      }

      .moveRowPointerTop {
        top: 0px;
      }

      .moveRowPointerBottom {
        bottom: 0px;
      }
    }

    .cell-index {
      position: absolute;
      text-align: center;
      background: #eee;
      border-right: 1px solid #ddd;
      border-bottom: 1px solid #ddd;
    }

    .edit-cells {
      position: absolute;

      .cells {
        position: absolute;
        border-right: 1px solid #ddd;
        border-bottom: 1px solid #ddd;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;

        span {
          padding: 0 4px;
        }

        :deep(.el-input) {
          margin: 0 0 3px 3px;

          .el-input__wrapper {
            padding: 0 1px;
            box-shadow: none;
            background: transparent;
          }

          .el-input__inner {
            font-family: "宋体";
          }
        }
      }
    }
  }

  .range-select {
    pointer-events: none;

    .range {
      position: absolute;
      border: 2px solid rgb(33, 115, 70);
    }

    .more {
      background: rgba(33, 115, 70, 0.3);
    }
  }
}
</style>
